package com.rc.saas.tenant.transfers.cb;


import com.rc.saas.tenant.transfers.jaxb.MarshallerListener;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Component;

import javax.xml.bind.*;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 中行银企接口统一接口
 * 第1步：根据中行提供的XML接口模板，使用IDEA自带的功能（右键generate XSD）生成XSD文件
 * 第2步：使用IDEA自带的功能(菜单TOOLS/JAXB/...)根据第1步的XSD生成JAVA对象
 * 第3步：使用JAXB库进行编组和解组，即BEAN<===>XML的转换
 * Created by Sven on 2021/08/26
 */
@Component
public class CbDelegate {
    private static Logger logger = LogManager.getLogger(CbDelegate.class);

    //中行前置机接口URL
    //@Value("${cb.transfer_api_url}")
    private String transfer_api_url = "http://127.0.0.1:8080/B2EC/";

    //@Value("${cb.transfer_api_encoding}")
    private String transfer_api_encoding = "UTF-8";

    /**
     * 公对公转账汇款(b2e0009)
     * 入参由 JAXBElement<T>的T决定
     * 出参由 R 决定
     */
    public <T, R> R call(JAXBElement<T> request, Class<T> clazz) throws JAXBException {
        String requestXml = null;
        String responseXml = null;
        //try {
        //JAXBContext是我们在使用JAXB时的入口类，我们需要通过它的实例来建立XML和Java类之间的映射关系，
        //需要通过它来创建用于转换Java对象到XML的Marshaller或是创建用于转换XML到Java对象的Unmarshaller
        JAXBContext context = JAXBContext.newInstance(clazz);
        Marshaller marshaller = context.createMarshaller();
        //设置编码等属性
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");

        //设置监听器
        MarshallerListener listener = new MarshallerListener();
        marshaller.setListener(listener);

        //BEAN转换成XML,输出到Write
        StringWriter write = new StringWriter();
        marshaller.marshal(request, write);

        System.out.println(write);

        requestXml = write.toString();

        Map<String, String> params = new HashMap<>();
        params.put("requestXml", requestXml);

        //TODO 先关闭
        //responseXml = doPost(params);

        //} catch (Exception e) {
        //    logger.error("b2e0009指令发送错误", e);
        //}

        //返回值,XML转BEAN
        R response = null;

        if (StringUtils.isNotBlank(responseXml)) {
            StringReader stringReader = new StringReader(responseXml);
            Unmarshaller unmarshaller = context.createUnmarshaller();

            response = (R) unmarshaller.unmarshal(stringReader);
        }

        //if (!StringUtils.equals("000000", response.gets())) {
        //    logger.error("调用建行接口异常，returnCode: {}, returnMsg: {}",
        //            response.getReturnCode(), response.getReturnMsg());
        //    throw new RuntimeException("调用接口异常：" + response.getReturnMsg());
        //}

        return response;
    }

    /**
     * 调用接口
     */
    private String doPost(Map<String, String> params) {
        return doPost(params, transfer_api_url, transfer_api_encoding);
    }

    /**
     * 调用接口
     */
    private String doPost(Map<String, String> params, String url, String encoding) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        try {
            httpClient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(url);
            if (params != null) {
                List<NameValuePair> parameters = new ArrayList<>(); //设置post参数
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    parameters.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                    logger.info("Request Message: {}", entry.getValue().replaceAll("<PASSWORD>[0-9a-zA-Z]*</PASSWORD>", "<PASSWORD>******</PASSWORD>"));
                }

                // 构造一个form表单式的实体
                UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters, encoding);

                // 将请求实体设置到httpPost对象中
                httpPost.setEntity(formEntity);
            }

            response = httpClient.execute(httpPost);
            String res = EntityUtils.toString(response.getEntity(), encoding);
            logger.info("Response Status: {} \n Response Message: {}", response.getStatusLine().getStatusCode(), res);

            return res;
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (null != response) {
                try {
                    response.close();
                } catch (IOException e) {
                    logger.error(e.getMessage(), e);
                }
            }
            if (null != httpClient) {
                try {
                    httpClient.close();
                } catch (IOException e) {
                    logger.error(e.getMessage(), e);
                }
            }
        }
    }
}